import java.util.Arrays;
import java.util.Map;


//       泛型

//问题
//  1.只能存放整数的数据 不通用 能不能啥都可以放
class MyArrayList2 {
    private int[] elem;
    private int usedSize;

    public MyArrayList2() {
        this.elem =new int[10];
        usedSize = 0;
    }

    public void add(int val) {
        this.elem[usedSize] = val;
        usedSize++;
    }
    public int get(int pos) {
        return this.elem[pos];
    }
}



//  2.我们知道所有类型的父类都是Object
//  但是如果我们使用Object：
//      1.存放元素 不能指定元素  什么元素都可以放进去
//      2.每次取出都需要将（Object）进行强制类型转换
class MyArrayList3 {
    private Object[] elem;
    private int usedSize;

    public MyArrayList3() {
        this.elem =new Object[10];
        usedSize = 0;
    }

    public void add(Object val) {
        this.elem[usedSize] = val;
        usedSize++;
    }
    public Object get(int pos) {
        return this.elem[pos];
    }
}
//  运行main3


//  3.
//  能不能指定顺序表的类型？
//  指定类型之后 是不是就只能放指定类型的数据呢？
//  取出的数据能不能 不要进行转换？
//
//      class MyArrayList<E> 尖括号代表当前类是一个泛型类  此时的这个E就是一个占位符而已
//      这里就用到泛型 把类型参数化main4
//
//  泛型的意义：
//1.自动对类型进行检查 main5
//2.自动对类型进行强制类型转换
class MyArrayList<E> {
    private E[] elem;
    private int usedSize;

    public MyArrayList() {
//        this.elem =new E[10];error
        this.elem = (E[])new Object[10];//虽然不会报错 但是这不是一个正确的写法
//        需要正确书写 需要用到反射的知识
        usedSize = 0;
    }

    public void add(E val) {
        this.elem[usedSize] = val;
        usedSize++;
    }
    public E get(int pos) {
        return this.elem[pos];
    }



    public Object[] getArray(int size) {
        Object[] genericArray = new Object[size];
        return genericArray;
    }
}




public class TestDemo2 {
    public static void main3(String[] args) {
        MyArrayList myArrayList2 = new MyArrayList();
        myArrayList2.add(1);
        myArrayList2.add(2);
        myArrayList2.add("hello");
        System.out.println(myArrayList2.get(1));//2
        System.out.println(myArrayList2.get(2));//hello
    }


    public static void main4(String[] args) {
        MyArrayList<String> myArrayList = new MyArrayList<String>();//后面的尖括号内可以不要写
        MyArrayList<Integer> myArrayList2 = new MyArrayList<>();
        MyArrayList<Boolean> myArrayList3 = new MyArrayList<>();

        System.out.println(myArrayList);//MyArrayList@1b6d3586
        System.out.println(myArrayList2);//MyArrayList@4554617c
        System.out.println(myArrayList3);//MyArrayList@74a14482
//        泛型中尖括号当中的内容  不参与类型的组成
//        面试问题：
//        泛型是怎么编译的?
//          1.泛型是编译时期的一种机制 擦除机制     就是在运行时<E>这部分就没有了
//                         里面的E被替换成成Object
    }

//    有个例子
//
//    public <T> T[] getArray(int size) {
//        T[] genericArray = new T[size];
//        return genericArray;
//    }
//    假设什么的代码成立有
    public Object[] getArray(int size) {
        Object[] genericArray = new Object[size];
            return genericArray;
        }//设这段代码是在MyArrayList里面
    public static void main123(String[] args) {
        MyArrayList<String> myArrayList = new MyArrayList<>();
        String[] rest = (String[]) myArrayList.getArray(1);
//      运行后错误  ClassCastException

//      所以：
//      数组和泛型之间的一个重要区别是它们如何强制执行类型检查，
//      具体来说，数组在运行时存储和检查类型信息然而，
//      泛型在编译时检查类型错误，并且在运行时没有类型信息。
//        文档https://www.baeldung.com/java-generic-array
    }










    public static void main5(String[] args) {
        MyArrayList<String> myArrayList = new MyArrayList<>();
        myArrayList.add("hello");
        myArrayList.add("world");
//        myArrayList.add(12);error
//        自动强制类型转换
        String ret = myArrayList.get(1);
        System.out.println(ret);//world

        MyArrayList<Integer> myArrayList2 = new MyArrayList();
        myArrayList2.add(12);
        myArrayList2.add(23);
        myArrayList2.add(34);
        int ret2 = myArrayList2.get(0);
        System.out.println(ret2);//12
    }
}
